package com.xuan.commons.config;

import com.xuan.commons.config.jwt.JWTFilter;
import com.xuan.commons.shiro.UserRealm;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author renzhengxuan
 * @date 2021/5/21
 * shiro配置类
 */
@Configuration
public class ShiroConfig {

    //创建shiroFilter,负责拦截所有请求
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        //给Filter设置安全管理器（因为请求都在安全管理器中拦截处理）
        factoryBean.setSecurityManager(securityManager);
        //配置系统的受限资源
        //配置系统的公共资源
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/user/login","anon");
        filterChainDefinitionMap.put("/user/register","anon");//注册放开
        //放行swagger
        filterChainDefinitionMap.put("doc.html","anon");
        filterChainDefinitionMap.put("/**/*.js", "anon");
        filterChainDefinitionMap.put("/**/*.css", "anon");
        filterChainDefinitionMap.put("/**/*.html", "anon");
        //swagger接口权限 开放
        filterChainDefinitionMap.put("/druid/**", "anon");
        filterChainDefinitionMap.put("/swagger-ui.html", "anon");
        filterChainDefinitionMap.put("/swagger**/**", "anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/v2/**", "anon");

        //添加token过滤器
        Map<String, Filter> filters = new LinkedHashMap<>();
        filters.put("jwt",new JWTFilter());
        factoryBean.setFilters(filters);
        //将value设置为jwt,意思就是除了上面的请求，其他都拦截，需要jwt认证，一般放在最下面
        filterChainDefinitionMap.put("/**","jwt");
        factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        //未经过授权跳转的接口(访问受限资源)
        factoryBean.setUnauthorizedUrl("/auth/401");
        factoryBean.setLoginUrl("/auth/401");
        return factoryBean;
    }
    //创建安全管理器 SecurityManager
    @Bean
    public DefaultWebSecurityManager securityManager(Realm realm){
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        //给安全管理器设置realm
        defaultWebSecurityManager.setRealm(realm);
        /*
         * 关闭shiro自带的session，详情见文档
         * http://shiro.apache.org/session-management.html#SessionManagement-
         * StatelessApplications%28Sessionless%29
         */
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        defaultWebSecurityManager.setSubjectDAO(subjectDAO);
        return defaultWebSecurityManager;
    }
    //创建自定义Realm(这个自定义Realm类用来进行授权和认证)
    @Bean
    public Realm getRealm(){
        UserRealm userRealm = new UserRealm();
        return userRealm;
    }
}
